/*
 * @Author jiangzhiwei
 * @Date 2023-07-18 14:57:59
 * @LastEditors jiangzhiwei
 * @LastEditTime 2023-07-28 18:01:45
 * @FilePath \test-cron\src\components\yc-cron\index.js
 * @Description cron表达式组件
 */
import { defineComponent } from 'vue-demi'
import { h } from './utils/domutil'
import { emitValue, resolveComponent } from './utils/componentutil'
import { getOptionDuration } from './utils/config'
import { QUARTS_TYPE, TAB_EMIT_NAME, VALUE_EMIT_NAME, VALUE_NAME, DAY_EXPRESSION_EMIT_NAME, WEEK_EXPRESSION_EMIT_NAME, LACK_FLAG } from './utils/constant'
import { setValue } from './utils/proputil'
import CommonTabs from './components/base/common-tabs'
import CommonTabPane from './components/base/common-tab-pane'
import SecondPane from './components/panes/second-pane'
import MinutePane from './components/panes/minute-pane'
import HourPane from './components/panes/hour-pane'
import DayPane from './components/panes/day-pane'
import MonthPane from './components/panes/month-pane'
import WeekPane from './components/panes/week-pane'
import YearPane from './components/panes/year-pane'
import ShowPane from './components/panes/show-pane'
import './css/main.css'
import { parseCron } from './utils/parse'
// import dayjs from 'dayjs'
// import { getBetweenDayOfWeeksOfMonth, getLastDayOfMonth, getLastWeekOfMonth, getLatestWeekdayOfMonth, getNthWeekOfMonth } from './utils/time'

export default defineComponent({
  components: { CommonTabs, CommonTabPane, SecondPane, MinutePane, HourPane, DayPane, MonthPane, WeekPane, YearPane, ShowPane },
  props: {
    /**
     * 类型。分为linux、spring、quarts。
     * 其中linux没有秒。linux、spring没有年
     * linux与spring的星期为0~7，分别为周日到周日；quarts的星期为1~7，分别为周日到周六
     */
    type: {
      type: String,
      default: QUARTS_TYPE
    },
    [VALUE_NAME]: {
      type: String,
      default: undefined
    },
    /** 各个组件的名字映射。自定义时需全局引入对应的标签页组件 */
    customNameMap: {
      type: Object,
      default: () => ({})
    },
    /** 年配置面板开始年份 */
    startYear: {
      type: Number,
      default: undefined
    },
    /** 年配置面板可选年份总数 */
    totalYear: {
      type: Number,
      default: undefined
    },
    /** 所有配置面板是否对齐高度 */
    alignHeight: {
      type: Boolean,
      default: true
    }
  },
  data () {
    return {
      /** 默认组件的名字映射 */
      nameMap: {
        tabsName: 'CommonTabs',
        tabPaneName: 'CommonTabPane',
        showPaneName: 'ShowPane'
      },
      expressionList: [],
      /** 选中标签 */
      activeTab: undefined
    }
  },
  computed: {
    realNameMap () {
      return Object.assign({}, this.nameMap, this.customNameMap)
    },
    componentMap () {
      return {
        pane: {
          'SecondPane': { label: 'SecondPane', title: '秒', index: 0 },
          'MinutePane': { label: 'MinutePane', title: '分', index: 1 },
          'HourPane': { label: 'HourPane', title: '时', index: 2 },
          'DayPane': { label: 'DayPane', title: '日', index: 3 },
          'MonthPane': { label: 'MonthPane', title: '月', index: 4 },
          'WeekPane': { label: 'WeekPane', title: '周', index: 5 },
          'YearPane': { label: 'YearPane', title: '年', index: 6 }
        }
      }
    },
    /** 所有tab页基本信息。根据type处理了几种类型的差异 */
    tabInfos () {
      const duration = getOptionDuration(this.type)
      const tabInfos =  Object.values(this.componentMap.pane)
      return tabInfos.slice(duration[0], duration[1])
    },
    optionDuration () {
      return getOptionDuration(this.type)
    }
  },
  watch: {
    [VALUE_NAME]: {
      handler () {
        this.expressionList = parseCron(this[VALUE_NAME], this.type)
      },
      immediate: true
    }
  },
  created () {
    this.activeTab = this.tabInfos[0].title
  },
  methods: {
    onInput () {
      const expression = this.expressionList.slice(this.optionDuration[0], this.optionDuration[1]).join(' ')
      emitValue(this, expression)
    },
    onTabChange (value) {
      this.activeTab = value
    },
    onExpressionChange (value, index) {
      setValue(this.expressionList, index, value)
      this.onInput()
    },
    /** 日对应的表达式变化 */
    onDayExpressionChange (value) {
      if (value && value !== LACK_FLAG && value !== '?') {
        setValue(this.expressionList, 5, '?') // 修改周为?
      }
    },
    /** 周对应的表达式变化 */
    onWeekExpressionChange (value) {
      if (value && value !== LACK_FLAG && value !== '?') {
        setValue(this.expressionList, 3, '?') // 修改日为?
      }
    },
    // onParseError (value, index) {
    //   const arr = Object.values(this.componentMap.pane).map(item => item.title)
    //   console.log('onParseError: ', value, arr[index])
    // }
  },
  render () {
    return h(
      'article',
      { class: 'yc-cron' },
      [
        h(
          resolveComponent(this.realNameMap.tabsName),
          {
            class: { 'is-align-height': this.alignHeight },
            props: { [VALUE_NAME]: this.activeTab },
            on: { [VALUE_EMIT_NAME]: this.onTabChange }
          },
          this.tabInfos.map(info => {
            return h(
              resolveComponent(this.realNameMap.tabPaneName),
              {
                props: { label: info.title }
              },
              [
                h(
                  resolveComponent(info.label),
                  {
                    props: {
                      [VALUE_NAME]: this.expressionList[info.index],
                      type: this.type,
                      // 年面板传递年份信息
                      ...(info.index === 6 ? { startNum: this.startYear, total: this.totalYear } : undefined)
                    },
                    on: {
                      [VALUE_EMIT_NAME]: value => this.onExpressionChange(value, info.index),
                      [DAY_EXPRESSION_EMIT_NAME]: this.onDayExpressionChange,
                      [WEEK_EXPRESSION_EMIT_NAME]: this.onWeekExpressionChange,
                      // [PARSE_ERROR_EMIT_NAME]: value => this.onParseError(value, info.index)
                    }
                  }
                )
              ]
            )
          })
        ),
        h(
          resolveComponent(this.realNameMap.showPaneName),
          {
            props: {
              type: this.type,
              expression: this[VALUE_NAME],
              activeTab: this.activeTab
            },
            on: {
              [VALUE_EMIT_NAME]: this.onInput,
              [TAB_EMIT_NAME]: this.onTabChange
            }
          }
        )
      ]
    )
  }
})
